<!-- 编辑弹窗 -->
<template>
  <RadModal :visible="visible" :loading="loading" :is-update="isUpdate" title="菜单" @visible-change="updateVisible"
    @ok="save">
    <a-form ref="formRef" :model="form" :rules="rules"
      :label-col="styleResponsive ? { md: 6, sm: 4, xs: 24 } : { flex: '90px' }" :wrapper-col="styleResponsive ? { md: 18, sm: 20, xs: 24 } : { flex: '1' }
        " noStyle>
      <a-row :gutter="16">
        <a-col v-bind="styleResponsive ? { md: 12, sm: 24, xs: 24 } : { span: 12 }">
          <a-form-item label="上级菜单" name="pid">
            <a-tree-select allow-clear :tree-data="menuList" :field-names="{ label: 'title', value: 'id' }"
              tree-default-expand-all placeholder="请选择上级菜单" :value="form.pid || undefined"
              :dropdown-style="{ maxHeight: '360px', overflow: 'auto' }"
              @update:value="(value?: number) => (form.pid = value)" />
          </a-form-item>
          <a-form-item label="菜单名称" name="title">
            <a-input allow-clear placeholder="请输入菜单名称" v-model:value="form.title" />
          </a-form-item>
        </a-col>
        <a-col v-bind="styleResponsive ? { md: 12, sm: 24, xs: 24 } : { span: 12 }">
          <a-form-item label="菜单类型" name="type">
            <a-radio-group v-model:value="form.type" @change="onMenuTypeChange">
              <a-radio :value="1">目录</a-radio>
              <a-radio :value="2">菜单</a-radio>
              <a-radio :value="3">按钮</a-radio>
            </a-radio-group>
          </a-form-item>
          <a-form-item name="path">
            <template #label>
              <a-tooltip v-if="form.openType === 2" title="需要以`http://`、`https://`、`//`开头">
                <question-circle-outlined style="vertical-align: -2px; margin-right: 4px" />
              </a-tooltip>
              <span>{{ form.openType === 2 ? '外链地址' : '路由地址' }}</span>
            </template>
            <a-input allow-clear v-model:value="form.path" :disabled="isButton(form.type)" :placeholder="form.openType === 2 ? '请输入外链地址' : '请输入路由地址'
              " />
          </a-form-item>
        </a-col>
      </a-row>
      <a-row :gutter="16">
        <a-col v-bind="styleResponsive ? { md: 12, sm: 24, xs: 24 } : { span: 12 }">
          <a-form-item label="菜单图标" name="icon">
            <ele-icon-picker :data="iconData" :allow-search="false" v-model:value="form.icon" placeholder="请选择菜单图标"
              :disabled="isButton(form.type)">
              <template #icon="{ icon }">
                <component :is="icon" />
              </template>
            </ele-icon-picker>
          </a-form-item>
          <a-form-item name="component">
            <template #label>
              <a-tooltip v-if="form.openType === 1" title="需要以`http://`、`https://`、`//`开头">
                <question-circle-outlined style="vertical-align: -2px; margin-right: 4px" />
              </a-tooltip>
              <span>{{ form.openType === 1 ? '内链地址' : '组件路径' }}</span>
            </template>
            <a-input allow-clear v-model:value="form.component" :disabled="isButton(form.type)" :placeholder="form.openType === 1 ? '请输入内链地址' : '请输入组件路径'
              " />
          </a-form-item>
          <a-form-item label="忽略缓存">
            <a-switch checked-children="是" un-checked-children="否" :checked="form.ignoreKeepAlive"
              :disabled="isButton(form.type)" @update:checked="(value: boolean) => {
                form.ignoreKeepAlive = value;
              }
                " />
          </a-form-item>
        </a-col>
        <a-col v-bind="styleResponsive ? { md: 12, sm: 24, xs: 24 } : { span: 12 }">
          <a-form-item label="权限标识" name="authority">
            <a-input allow-clear placeholder="请输入权限标识" v-model:value="form.permission" :disabled="!isButton(form.type)" />
          </a-form-item>
          <a-form-item label="排序号" name="order">
            <a-input-number :min="0" :max="99999" class="ele-fluid" placeholder="请输入排序号" v-model:value="form.order" />
          </a-form-item>
          <a-form-item label="是否展示">
            <a-switch checked-children="是" un-checked-children="否" :checked="!form.hide" :disabled="isButton(form.type)"
              @update:checked="(value: boolean) => {
                form.hide = !value
              }" />
            <a-tooltip title="选择不展示只注册路由不展示在侧边栏, 比如添加页面应该选择不展示">
              <question-circle-outlined style="vertical-align: -4px; margin-left: 16px" />
            </a-tooltip>
          </a-form-item>
        </a-col>
      </a-row>
    </a-form>
  </RadModal>
</template>

<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { message } from 'ant-design-vue/es';
import type { FormInstance, Rule } from 'ant-design-vue/es/form';
import { QuestionCircleOutlined } from '@ant-design/icons-vue';
import RadModal from '@/components/RadModal/index.vue';
import { storeToRefs } from 'pinia';
import { useThemeStore } from '@/store/modules/theme';
import useFormData from '@/utils/use-form-data';
import { addMenu, updateMenu } from '@/api/system/menu';
import type { Menu } from '@/api/system/menu/model';

// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);

const emit = defineEmits<{
  (e: 'done'): void;
  (e: 'update:visible', visible: boolean): void;
}>();

const props = defineProps<{
  // 弹窗是否打开
  visible: boolean;
  // 修改回显的数据
  data?: Menu | null;
  // 上级菜单id
  parentId?: number;
  // 全部菜单数据
  menuList: Menu[] | undefined;
}>();
const isButton = (type: number | undefined) => type === 3;
//
const formRef = ref<FormInstance | null>(null);

// 是否是修改
const isUpdate = ref(false);

// 提交状态
const loading = ref(false);

// 表单数据
const { form, resetFields, assignFields } = useFormData<Menu>({
  id: undefined,
  pid: undefined,
  title: '',
  type: 1,
  openType: 0,
  icon: '',
  path: '',
  component: '',
  permission: '',
  order: undefined,
  hide: false,
  meta: '',
  ignoreKeepAlive: false
});

// 表单验证规则
const rules = reactive<Record<string, Rule[]>>({
  title: [
    {
      required: true,
      message: '请输入菜单名称',
      type: 'string',
      trigger: 'blur'
    }
  ],
  sortNumber: [
    {
      required: true,
      message: '请输入排序号',
      type: 'number',
      trigger: 'blur'
    }
  ],
  meta: [
    {
      type: 'string',
      validator: async (_rule: Rule, value: string) => {
        if (value) {
          const msg = '请输入正确的JSON格式';
          try {
            const obj = JSON.parse(value);
            if (typeof obj !== 'object' || obj === null) {
              return Promise.reject(msg);
            }
          } catch (_e) {
            return Promise.reject(msg);
          }
        }
        return Promise.resolve();
      },
      trigger: 'blur'
    }
  ]
});

/* 保存编辑 */
const save = () => {
  if (!formRef.value) {
    return;
  }
  formRef.value
    .validate()
    .then(() => {
      loading.value = true;
      const menuForm = {
        ...form,
        // menuType 对应的值与后端不一致在前端处理
        //menuType: form.type === 2 ? 1 : 0,
        //parentId: form.pid || 0,
        //isHide: form.hideMenu
      };
      const saveOrUpdate = isUpdate.value ? updateMenu : addMenu;
      saveOrUpdate(menuForm)
        .then((msg) => {
          loading.value = false;
          message.success(msg);
          updateVisible(false);
          emit('done');
        })
        .catch((e) => {
          loading.value = false;
          message.error(e.message);
        });
    })
    .catch(() => { });
};

/* 更新visible */
const updateVisible = (value: boolean) => {
  emit('update:visible', value);
};

/* menuType选择改变 */
const onMenuTypeChange = () => {
  if (form.type === 0) {
    form.permission = '';
    form.openType = 0;
    form.component = '';
  } else if (form.type === 1) {
    if (form.openType === 2) {
      form.permission = '';
    }
  } else {
    form.openType = 0;
    form.icon = '';
    form.path = '';
    form.component = '';
    form.hide = false;
  }
};

watch(
  () => props.visible,
  (visible) => {
    if (visible) {
      if (props.data) {
        //const isExternal = isExternalLink(props.data.path);
        //const isInner = isExternalLink(props.data.component);
        // menuType 对应的值与后端不一致在前端处理
        //const menuType =
        //props.data.type === 1 ? 2 : isDirectory(props.data) ? 0 : 1;
        assignFields({
          ...props.data
          //menuType,
          //openType: isExternal ? 2 : isInner ? 1 : 0,
          //parentId: props.data.pid === 0 ? undefined : props.data.pid
        });
        isUpdate.value = true;
      } else {
        form.pid = props.parentId;
        isUpdate.value = false;
      }
    } else {
      resetFields();
      formRef.value?.clearValidate();
    }
  }
);
</script>

<script lang="ts">
import * as icons from '@/layout/menu-icons';

export default {
  components: icons,
  data() {
    return {
      iconData: [
        {
          title: '已引入的图标',
          icons: Object.keys(icons)
        }
      ]
    };
  }
};
</script>
